﻿using SUNRPA.CONTROLS.IMPL.domain;
using SUNRPA.CONTROLS.IMPL.domain.constant;
using SUNRPA.CONTROLS.IMPL.domain.flowItemParam;
using RPAVIEW.domain;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Collections.Concurrent;
using RPAVIEW.util;
using System.Collections.Generic;
using SUNRPA.CONTROLS.IMPL.domain.flowRunningVar;

namespace RPAVIEW.views.EditPage.flows {
    /// <summary>
    /// FlowEditWindow.xaml 的交互逻辑
    /// </summary>
    public partial class FlowEditWindow:Window {
        private TreeViewItem targetControl;
        private EditHome parentControl;
        private Boolean isEdit = false;
        private Boolean isInsert = false;
        private int insertIndex = -1;
        private int editIndex = -1;
        private List<RPAVariableDefineWrapper> waitForCompleteInfo = new List<RPAVariableDefineWrapper> ();
        public void AddDefinedVar(RPAVariableDefineWrapper var) { 
            waitForCompleteInfo.Add (var);
        }
        public FlowEditWindow(TreeViewItem tc, EditHome parentC) {
            InitializeComponent();
            targetControl = tc;
            parentControl = parentC;
            TreeNodes targetNode = (TreeNodes)tc.Header;
            this.tip.Text = targetNode.Tip;
            this.Title = targetNode.Name;
            //利用反射获取对话框的参数组件
            string basePath = BaseNameSpace.FLOW_VIEW_BASE_PATH+targetNode.Key;
            Type param = Type.GetType(BaseNameSpace.FLOW_PARAM_BASE_PATH + targetNode.Key + "Param," + DefaultContents.PROJECT_NAME);
            if(param != null) { 
                Object paramObj = Activator.CreateInstance(param);
                //更新默认输出变量名称（递增）
                ((BaseParam)paramObj).SetLatestVarName(parentC.DataContext as ConcurrentDictionary<string, ConcurrentDictionary<string, RPAVariableDefineWrapper>>);
                //创建参数对象，绑定到datacontext上
                this.DataContext = paramObj;
            }
            
            Type input = Type.GetType(basePath+".Input");
            Type output = Type.GetType(basePath+".Output");
            Type advance = Type.GetType(basePath+".Advance");

            UserControl inputObj = null;
            if(input == null){
                inputObj = new EmpytInPut();
            } else { 
                inputObj = (UserControl)Activator.CreateInstance(input);
            }
            this.General.input.Children.Add(inputObj);

            UserControl outputObj = null;
            if(output != null){
                outputObj = (UserControl)Activator.CreateInstance(output);
            }else { 
                outputObj = new EmpytOutPut();
            }
            this.General.output.Children.Add(outputObj);

            UserControl advanceObj = null;
            if(advance != null) { 
                advanceObj = (UserControl)Activator.CreateInstance(advance);
                this.Advance.advanceContent.Children.Add(advanceObj);  
            } else { 
                this.AdvanceTab.Visibility = Visibility.Collapsed;
            }
            
        }
        public FlowEditWindow(FlowItem flowItem) {
            InitializeComponent();
            this.tip.Text = flowItem.EditTip;
            this.Title = flowItem.EditTitle;
            this.isEdit = true;
            this.editIndex = flowItem.Index;
            //创建参数对象，绑定到datacontext上
            this.DataContext = flowItem.ControlParam;
            //利用反射获取对话框的参数组件
            string basePath = BaseNameSpace.FLOW_VIEW_BASE_PATH + flowItem.ControlKey;
            Type input = Type.GetType(basePath+".Input");
            Type output = Type.GetType(basePath+".Output");
            Type advance = Type.GetType(basePath+".Advance");
            UserControl inputObj = (UserControl)Activator.CreateInstance(input);
            this.General.input.Children.Add(inputObj);
            UserControl outputObj = null;
            if(output != null){
                outputObj = (UserControl)Activator.CreateInstance(output);
            }else { 
                outputObj = new EmpytOutPut();
            }
            this.General.output.Children.Add(outputObj);
            UserControl advanceObj = null;
            if(advance != null) { 
                advanceObj = (UserControl)Activator.CreateInstance(advance);
                this.Advance.advanceContent.Children.Add(advanceObj);  
            } else { 
                this.AdvanceTab.Visibility = Visibility.Collapsed;
            }
        }

        public TreeViewItem TargetControl { get => targetControl; set => targetControl = value; }
        public bool IsInsert { get => isInsert; set => isInsert = value; }
        public int InsertIndex { get => insertIndex; set => insertIndex = value; }
        public int EditIndex { get => editIndex; set => editIndex = value; }

        private void CloseWindow(object sender, RoutedEventArgs e) {
            this.Close();
        }

        //创建流程节点
        private void GenertFlowItem(object sender, RoutedEventArgs e) {
            UpdateSource();
            if(!this.isEdit) {
                Dictionary<string,string> key2name = ParamUtil.GetAppGlobleVar<Dictionary<string,string>>(DefaultContents.FUNCTION_TREE_NAME);
                TreeNodes targetNode = (TreeNodes)targetControl.Header;
                FlowItem item = new FlowItem();
                foreach(var waitcom in waitForCompleteInfo) { 
                    waitcom.FlowItem = item;
                }
                item.EditTip = targetNode.Tip;
                item.EditTitle = targetNode.Name;
                item.ControlName = targetNode.Name;
                item.ControlKey = targetNode.Key;
                item.ParentKey = targetNode.ParentKey;
                item.ControlType = BaseNameSpace.FLOW_PARAM_BASE_PATH + targetNode.Key + "Param," +  DefaultContents.PROJECT_NAME;
                item.ControlParam = (BaseParam)this.DataContext;
                item.ItemInfo = targetNode.ItemInfo;
                FlowItemView fv = new FlowItemView(item);
                fv.DataContext = item;
                fv.itemTitle.Text = targetNode.Name;
                //如果该控件包含结束标签则需要需要创建结束标签的视图
                FlowItem endTag = null;
                FlowItemView endTagView = null;
                if(!string.IsNullOrEmpty(targetNode.EndTag)) { 
                    endTag = new FlowItem();
                    item.EndTag = endTag;
                    endTag.ControlKey = targetNode.Key;
                    endTag.ItemInfo = targetNode.EndTag;
                    endTagView = new FlowItemView(endTag);
                    endTagView.DataContext = endTag;
                    endTagView.itemTitle.Text = targetNode.EndTag;
                    fv.EndTagView = endTagView;
                }
                if(isInsert) {
                    int insertStep = 1;
                    //查看当前插入索引前面有多少个双标记标签，有多少个则需要缩进多少个空格
                    int doubleCount = 0;
                    for(int i = 0; i < insertIndex; i++){
                        FlowItemView preView = parentControl.FlowItems.Children[i] as FlowItemView;
                        FlowItem preItem = preView.DataContext as FlowItem;
                        if(preItem.EndTag != null && preItem.EndTag.Index >= insertIndex && string.IsNullOrEmpty(preItem.ParentKey)) { 
                            doubleCount++;
                        }
                    }

                    //如果插入并且有parentKey，则表示这个控件必须直接存在于parentkey控件之内，即第一个双标记标签就是parentkey
                    if(!string.IsNullOrEmpty(targetNode.ParentKey)) { 
                        for(int i = insertIndex - 1; i >= 0; i--){
                            FlowItemView preView = parentControl.FlowItems.Children[i] as FlowItemView;
                            FlowItem preItem = preView.DataContext as FlowItem;
                            if(preItem.EndTag != null && preItem.EndTag.Index >= insertIndex) {
                                if(!preItem.ControlKey.Equals(targetNode.ParentKey)) {
                                    throw new RpaBuildingException($"此控件必须直接存在于控件{key2name[targetNode.ParentKey]}之内");
                                }
                                doubleCount--;
                                break;
                            }
                        }
                    }

                    parentControl.FlowItems.Children.Insert(insertIndex, fv);
                    //缩进
                    fv.Margin = new Thickness(doubleCount * 20, 0, 0, 0);
                    item.Index = insertIndex;
                    if(endTagView != null) { 
                        insertStep = 2;
                        parentControl.FlowItems.Children.Insert(insertIndex + 1, endTagView);
                        endTag.Index = insertIndex + 1;
                        endTagView.Margin = new Thickness(doubleCount * 20, 0, 0, 0);
                    }
                    for(int i = insertIndex + insertStep; i < parentControl.FlowItems.Children.Count; i++) { 
                        FlowItemView fiv =  (FlowItemView)parentControl.FlowItems.Children[i];
                        FlowItem changeIndexItem = fiv.DataContext as FlowItem;
                        changeIndexItem.Index = changeIndexItem.Index + insertStep;
                    }
                } else {
                    //如果不是插入是直接放置的话，则此控件不能包含parentKey
                    if(!string.IsNullOrEmpty(targetNode.ParentKey)) {
                        throw new RpaBuildingException($"此控件必须放在{key2name[targetNode.ParentKey]}控件内");
                    }
                    item.Index = parentControl.FlowItems.Children.Add(fv);
                    if(endTagView != null) { 
                        endTag.Index = parentControl.FlowItems.Children.Add(endTagView);
                    }
                }
            } else { 
                //编辑由于会删除原来定义的变量所以需要重新为变量的flowitem赋值
                FlowItem item = (FlowItem)(((FlowItemView)WindowUtil.GetCurrentEditHome().FlowItems.Children[editIndex]).DataContext);
                foreach(var waitcom in waitForCompleteInfo) { 
                    waitcom.FlowItem = item;
                }
            }
            this.Close();
        }

        private void UpdateSource() {
            foreach(Object input in this.General.input.Children){
                if(input is BaseParamViewAction) {
                    ((BaseParamViewAction)input).UpdateSource();
                }
            } 
            foreach(Object output in this.General.output.Children){ 
                if(output is BaseParamViewAction) {
                    ((BaseParamViewAction)output).UpdateSource();
                }
            } 
            foreach(Object advance in this.Advance.advanceContent.Children){ 
                if(advance is BaseParamViewAction) {
                    ((BaseParamViewAction)advance).UpdateSource();
                }
            } 
            ((BaseParamViewAction)this.Exception).UpdateSource();
        }
    }
}
